<?php

class View
{
    /**
    * Armazena o conteúdo HTML
    * @var string
    */
    private $contents;
     
    /**
    * Armazena o nome do arquivo de visualização
    * @var string
    */
    private $viewFile;
    
    /**
    * Armazena o nome do theme de visualização
    * @var string
    */
    private $theme;
    
     /**
    * Armazena o nome do layout de visualização
    * @var string
    */
    private $layout;
     
    /**
    * Armazena os dados que devem ser mostrados ao reenderizar o 
    * arquivo de visualização
    * @var Array
    */
    private $params;
    
    /**
    * Armazena a lista de javascripts devem ser mostrados ao reenderizar o 
    * arquivo de visualização
    * @var Array
    */
    private $listCustomJavascripts;
     
    /**
    * É possivel efetuar a parametrização do objeto ao instanciar o mesmo,
    * $st_view é o nome do arquivo de visualização a ser usado e 
    * $v_params são os dados que devem ser utilizados pela camada de visualização
    * 
    * @param string $view
    * @param Array $params
    */
    public function __construct($viewFile = null, $params = null, $theme = null, $layout = null) 
    {
        if($viewFile != null)
        {
            $this->setViewFile($viewFile);
        }
        $this->listCustomJavascripts = array();   
        $this->params = $params;
        $this->theme = (isset($theme))? $theme : null;
        $this->layout = (isset($layout))? $layout : 'layout.html';
    }   
     
    /**
    * Define qual arquivo html deve ser renderizado
    * @param string $st_view
    * @throws Exception
    */
    public function setViewFile($viewFile)
    {
        if(file_exists($viewFile))
            $this->viewFile = $viewFile;
        else
            throw new Exception("View File '$viewFile' don't exists");       
    }
     
    /**
    * Retorna o nome do arquivo que deve ser renderizado
    * @return string 
    */
    public function getViewFile()
    {
        return $this->viewFile;
    }
    
   /**
    * Define qual arquivo html deve ser renderizado
    * @param string $theme
    * @throws Exception
    */
    public function setTheme($theme)
    {
        if(file_exists("themes/{$theme}/layout.html"))
            $this->theme = $theme;
        else
            throw new Exception("Theme File '$theme' don't exists");       
    }
     
    /**
    * Retorna o nome do arquivo que deve ser renderizado
    * @return string 
    */
    public function getTheme()
    {
        return $this->theme;
    }
    
    public function getTemplatePath()
    {
        $templatePath = (isset($this->theme))? "themes/{$this->theme}" : TEMPLATE_PATH;
        return $templatePath;
    }
    
    public function getJSPath()
    {
        $jsPath = (isset($this->theme))? "themes/{$this->theme}/assets/scripts" : TEMPLATE_CUSTOM_JS_PATH;
        return $jsPath;
    }
    
    /**
    * Define qual arquivo html deve ser renderizado
    * @param string $theme
    * @throws Exception
    */
    public function setLayout($file)
    {
        if(file_exists($this->getTemplatePath().'/'.$file))
            $this->layout = $file;
        else
            throw new Exception("Layout File '$file' don't exists");       
    }
     
    /**
    * Retorna o nome do arquivo que deve ser renderizado
    * @return string 
    */
    public function getLayout()
    {
        return $this->layout;
    }
     
    /**
    * Define os dados que devem ser repassados à view
    * @param Array $v_params
    */
    public function setParams(Array $params)
    {
        $this->params = $params; 
    }
     
    /**
    * Retorna os dados que foram ser repassados ao arquivo de visualização
    * @return Array
    */
    public function getParams()
    {
        return $this->params;
    }
     
    /**
    * Retorna uma string contendo todo 
    * o conteudo do arquivo de visualizavßv£o
    * 
    * @return string
    */
    private function getContents()
    {
        ob_start();
        if(isset($this->viewFile))
        {
            include $this->viewFile;
        }
        $this->contents = ob_get_contents();
        ob_end_clean();
        return $this->contents;   
    }
    
    /**
    * Retorna uma string contendo todo 
    * o conteudo do arquivo 
    * 
    * @return string
    */
    private function getContentsLayoutFile($file)
    {
        $templatePath = $this->getTemplatePath();
        ob_start();
        if(isset($this->viewFile))
        {            
            include $templatePath."/".$file;
        }
        $output = ob_get_contents();
        ob_end_clean();   
        
        return $output;   
    }
    
    /**
    * Retorna uma string contendo todo 
    * o conteudo do arquivo 
    * 
    * @return string
    */
    private function getContentsJSFile($file)
    {
        $path = $this->getJSPath();
        $output = '<script src="'.SERVER_NAME.'/'.$path.'/'.$file.'" type="text/javascript"></script>';  
        
        return $output;   
    }
    
    private function getCustomJavascripts()
    {
        $customJS = " ";
        foreach($this->listCustomJavascripts as $item)
        {
            $customJS  = $customJS . " ". $this->getContentsJSFile($item);
        }
        return $customJS;
    }
    
    public function addCustomJSFile($item)
    {
        $this->listCustomJavascripts[] = $item;
    }
    
    /**
    * Retorna uma string contendo todo 
    * o conteudo do site HTML
    * 
    * @return string
    */
    private function displayHtml()
    {
        $outputHtml  = "";
        $content =  $this->getContents();
        
                    
        $layout  = $this->getContentsLayoutFile($this->layout);
        $head  = $this->getContentsLayoutFile("head.html");
        $javascript  = $this->getContentsLayoutFile("javascript.html");
        $customJavascript = $this->getCustomJavascripts();
        $css  = $this->getContentsLayoutFile("css.html");
        $menu  = $this->getContentsLayoutFile("menu.html");        
        $topMenu = $this->getContentsLayoutFile("topmenu.html");
        $user = Authenticate::UserIdentity();
        $menuMain = Menu::RenderMainMenu();
        
        $outputHtml  = str_replace('@LayoutMenu', $menu, $layout);
        $outputHtml  = str_replace('@LayoutMenuWithPermission', $menuMain, $outputHtml);
        $outputHtml  = str_replace('<!--{TOP_MENU}-->', $topMenu, $outputHtml);
        $outputHtml  = str_replace('<!--{CONTENT}-->', $content, $outputHtml);
        $outputHtml  = str_replace('<!--{TITLE}-->', APPLICATION_NAME, $outputHtml);
        $outputHtml  = str_replace('<!--{HEAD}-->', $head, $outputHtml);
        $outputHtml  = str_replace('<!--{JAVASCRIPT}-->', $javascript.$customJavascript, $outputHtml);
        $outputHtml  = str_replace('<!--{CSS}-->', $css, $outputHtml);
        $outputHtml  = str_replace('<!--{SERVER}-->', SERVER_NAME, $outputHtml);
        $outputHtml  = str_replace('<!--{TEMPLATE}-->', TEMPLATE_PATH, $outputHtml);
        if (isset($user)){
            $outputHtml  = str_replace('<!--{USER.NAME}-->', $user->name, $outputHtml);
        }
            echo $outputHtml;
    }
    
    /**
    * Retorna uma string contendo todo 
    * o conteudo do site JSON
    * 
    * @return string
    */
    private function displayJSON()
    {
        header('Content-type: application/json');
        echo json_encode($this->params);       
    }
     
    /**
     * Imprime o arquivo de visualização 
     * @return string
     * @param type $type
     */
    public function show($type = "html")
    {
        if ($type == "html")
            $this->displayHTML();
        
        if ($type == "json")
            $this->displayJSON();
    }
   
}
